using System;
using System.Collections.Generic;
using System.Text;
using agsXMPP;
using agsXMPP.protocol.client;
using agsXMPP.protocol.iq.roster;

namespace PoshXmpp
{
    public class ContactManager
    {
        List<Presence> _subscribeRequests = new List<Presence>();
        List<Jid> _onlineContacts = new List<Jid>();
        XmppClient _client;

        /// <summary>
        /// Default constructor
        /// </summary>
        /// <param name="client">The <see cref="XmppClientConnection"/></param>
        public ContactManager(XmppClient client)
        {
            _client = client;
            _client.OnPresence += new PresenceHandler(OnClientPresenceReceived);
            _client.OnAgentItem += new XmppClientConnection.AgentHandler(OnClientAgentItem);
            _client.OnRosterItem += new XmppClientConnection.RosterHandler(OnClientRosterItem);
            _client.OnRosterStart += new ObjectHandler(OnClientRosterStart);
            _client.OnRosterEnd += new ObjectHandler(OnClientRosterComplete);
        }

        void OnClientRosterComplete(object sender)
        {
            System.Diagnostics.Trace.WriteLine("Roster Start");
        }

        void OnClientRosterItem(object sender, agsXMPP.protocol.iq.roster.RosterItem item)
        {
            System.Diagnostics.Trace.WriteLine(String.Format( "Roster Item:\n{0}", item.InnerXml));

        }

        void OnClientRosterStart(object sender)
        {
            System.Diagnostics.Trace.WriteLine("Roster Start");
        }

        void OnClientAgentItem(object sender, agsXMPP.protocol.iq.agent.Agent agent)
        {
            System.Diagnostics.Trace.WriteLine("Agent Item" + (agent.IsGroupchat ? " for group chat:" : ":") + agent.InnerXml);
        }

        private void OnClientPresenceReceived(object sender, agsXMPP.protocol.client.Presence pres)
        {
            Jid bare = new Jid(pres.From.Bare.ToLower());

            switch (pres.Type)
            {
                case PresenceType.subscribe:
                    _subscribeRequests.Add(pres);
                    break;
                case PresenceType.subscribed:
                    break;
                case PresenceType.unsubscribe:
                    break;
                case PresenceType.unsubscribed:
                    break;
                case PresenceType.probe:
                    break;
                case PresenceType.unavailable:
                    if (_client.ChatManager.IsInRoom(bare))
                    {
                        _client.ChatManager.RemoveUser(bare, pres.From);
                    }
                    else
                    {
                        _onlineContacts.Remove(pres.From);
                    }
                    
                    break;
                // case PresenceType.available:
                // case PresenceType.invisible:
                // case PresenceType.error:
                default:
                    if (_client.ChatManager.IsInRoom(bare))
                    {
                        _client.ChatManager.AddUser(bare, pres.From, pres.From.Resource);
                    }
                    else
                    {
                        _onlineContacts.Add(pres.From);
                    }
                    break;
            }
        }




        public void Accept(Presence Request) 
        {
            _client.PresenceManager.ApproveSubscriptionRequest(Request.From);
            _client.PresenceManager.Subcribe(Request.From);
            _subscribeRequests.Remove(Request);
        }

        public void Refuse(Presence Request)
        {
            _client.PresenceManager.RefuseSubscriptionRequest(Request.From);
            _client.PresenceManager.Unsubcribe(Request.From);
            _subscribeRequests.Remove(Request);
        }


        public void AddContact(Jid From)
        {
            _client.PresenceManager.ApproveSubscriptionRequest(From);
            _client.PresenceManager.Subcribe(From);
            _subscribeRequests.RemoveAll( request => request.From.Bare.ToLower().Equals(From.Bare.ToLower()) );
        }

        public void RemoveContact(Jid From)
        {
            _client.PresenceManager.RefuseSubscriptionRequest(From);
            _client.PresenceManager.Unsubcribe(From);
            _subscribeRequests.RemoveAll( request => request.From.Bare.ToLower().Equals(From.Bare.ToLower()) );
        }


        /// <summary>
        /// True if there are requests in the queue, False otherwise
        /// </summary>
        public bool HasSubscriptionRequests
        {
            get
            {
                return _subscribeRequests.Count > 0;
            }
        }

        /// <summary>
        /// Enumerator for online buddies
        /// </summary>
        public IEnumerable<Jid> OnlineContacts
        {
            get
            {
                foreach (Jid item in _onlineContacts)
                {
                    yield return item;
                }
            }
        }

        /// <summary>
        /// Enumerator for messages in the queue
        /// </summary>
        public IEnumerable<Presence> Requests
        {
            get
            {
                foreach (Presence item in _subscribeRequests)
                {
                    yield return item;
                }
            }
        }


        public List<Jid> Contacts
        {
            get
            {
                return _onlineContacts;
            }
        }

        public List<Presence> ContactRequests
        {
            get { return _subscribeRequests; }
            //set { _subscribeRequests = value; }
        }
    }
}
